package class02;

/**
 * @description:
 * @time: 2021/7/3 18:54
 * @author: lhy
 */
public class RandomTest {
    public static double getTestRandomProbability(int testTimes,double condition,int multiple){
        int count = 0;
        for (int i = 0; i < testTimes; i++) {
            if (Math.random() * multiple < condition) {
                count++;
            }
        }
        return (double) count / testTimes;
    }

    /** 对于任意的 x ∈[0,1)
     *  让 [0,x)范围上的数出现的概率由原来的 x 调整为 x^2
     * @return [0,1)之间的小数
     */
    public static double xToPower2(){
        return Math.max(Math.random(),Math.random());
    }


    /**面试题 1：给你一个函数 f() ，如何不借助Math.random()机制，等概率返回[1,7]之间的整数
     * 此 f() 函数只能调用，不能修改
     * @return 等概率返回[1,5]之间的整数
     */
    public static int f(){
        return (int) (Math.random() * 5 + 1);
    }

    /**
     * 0,1等概率生成器
     * @return 0 or 1
     */
    public static int f1(){
        int ans;
        do {
            ans = f();
        }while (ans == 3);
        return ans < 3 ? 0 : 1;
    }

    /** 根据 f1() 函数可以得到0，1，用二进制表示十进制
     * 等概率返回[0,7]之间的整数
     * @return [0,7] int
     */
    public static int f2(){
        return (f1() << 2) + (f1() << 1) + f1();
    }

    /**
     * 目标函数 g() 等概率返回[1,7]之间的整数
     * @return [1,7] int
     */
    public static int g(){
        int ans;
        do {
            ans = f2();
        }while (ans == 7);
        return ans + 1;
    }


    public static void main(String[] args) {
        int testTimes = 1000000;
        double p = getTestRandomProbability(testTimes,0.4,1);
        System.out.println(">>>Test Random 0.4 : " + p);

        System.out.println(">>>Test Random [0,8):");
        p = getTestRandomProbability(testTimes,5,8);
        System.out.println("Probability of experiment:" + p);
        System.out.println("Probability of theory:" + 5.0 / 8);

        System.out.println(">>>Test Random [0,8]:");
        // [0,1) -> [0,8]之间的整数等概率出现 理论值为 1/9
        int k = 9;
        int[] counts = new int[k];
        for (int i = 0; i < testTimes; i++) {
            int ans = (int) (Math.random() * k);
            counts[ans]++;
        }
        for (int i = 0; i < k; i++) {
            System.out.println("P("+ i + ") = " + (double) counts[i] / testTimes);
        }
        System.out.println("P(i) = " + 1.0 / 9);

        System.out.println(">>>Test Random x^2:");
        int count = 0;
        double x = 0.6445;
        for (int i = 0; i < testTimes; i++) {
            if (xToPower2() < x){
                count++;
            }
        }
        p = (double)count / testTimes;
        System.out.println(p);
        System.out.println(Math.pow(x,2));

        System.out.println(">>> Test Random from [1,5] to [1,7]: ");
        counts = new int[8];
        for (int i = 0; i < testTimes; i++) {
            int ans = g();
            counts[ans]++;
        }
        for (int i = 0; i < 8; i++) {
            System.out.println("P("+ i + ") = " + (double) counts[i] / testTimes);
        }
        System.out.println("P(i) = " + 1.0 / 7);

    }
}
